Так устроит?
Вид для печати
Вот так устроит, если вы хотите удобства для читателей:
http://s017.radikal.ru/i417/1111/b3/8f6df96b4323.png
Вот про то, как будет читаться по адресам, отличным от 0,801h,1002h,1803h... поподробнее. Или для старших адресов всё-таки регистр с мультиплексором будет?
---------- Post added at 00:02 ---------- Previous post was at 00:00 ----------
Не, лучше два регистра с трёхстабильным выходом, а то много мультиплексоров надо будет.
---------- Post added at 00:03 ---------- Previous post was at 00:02 ----------
Или регистр и шинный формирователь.
Я боюсь, что любой внешний сайт через 10 лет пропадет. А статьи на этом сайте живут гораздо дольше. Я очень не хочу, что бы тема осталась, а схемы исчезли.
Я сейчас размышляю, как устроить чтение. Для управления входом R/С я уже передумал использовать линии A11,A12. Я буду использовать A14, A15, так легче писать программу. И микросхему 155ЛА3 заменю на 155ЛЕ1 (ИЛИ НЕ).
; A0-A10, 14 бит - это спад R/C, 15 бит - это блокирование генератора
ld hl, 0F800H
ld (0EE01h), hl
; A11-A19, 14 бит - это подъем R/C, 15 бит - это блокирование генератора
push hl
ld hl, 0B800H
ld (0EE01h), hl
pop hl
ld a, (0EE00h)
---------- Post added at 22:22 ---------- Previous post was at 22:19 ----------
Или с переменными:
readByte:
ld (0EE01h), hl ; A0-A10, 15 бит - это спад R/C, 14 бит - это блокирование генератора
push hl ; A11-A19, 15 бит - это подъем R/C, 14 бит - это блокирование генератора
ld hl, (bank)
ld (0EE01h), hl
pop hl
inc l
call z, incBank
ld a, (0EE00h)
ret
bank dw 0B800H
incBank:
inc h
ret nz
ld hl, 0F800h
inc (bank)
ret
---------- Post added at 22:27 ---------- Previous post was at 22:22 ----------
Хочется как можно проще. 155ЛЕ1 + ПЗУ
UPD: Эта схема устарела, ищи новую дальше по форуму.
http://s017.radikal.ru/i418/1111/63/33686d7dc0cb.png
А почему не завести R/C на сободную адресную линию типа A15, и таким образом не управлять процессом? Безо всяких генераторов?
То есть монитор будет читать загрузчик по адресам 0,801h,1002h,1803h... а уж этот загрузчик будет читать остальное? Не слишком ли сложно будет потом пропускать эти байты при нормальном чтении?
Да.
Архиватор работает последовательно, поэтому сложности пропускать 1 байт не составит. Условие типа:
if(bank==offset) offset++;
Сложность, сделать это без заметных тормозов. Я сейчас как раз над этим думаю.
Можно еще начинать чтение каждой страницы со смещения 1. А потом этот адрес чтения XOR-ить на номер банка. Таким образом мы никогда не обратимся к адресам: 0,801h,1002h,1803h
---------- Post added at 23:54 ---------- Previous post was at 23:42 ----------
Начальный загрузчик будет размером всего 35 байт, следовательно для программ размещенных после адреса 35 * 2048 + 35 = 71715 не требуется пропускать байт. И можно применить упрощенный и более быстрый загрузчик.
А что читается на шине данных, при R/C = 0? Там предыдущие данные, или же Z-состояние?
предыдущие данные
Я об этом уже думал :) Только я хотел соединить OE и R/C, что бы каждый второй байт был нулевым. Написать такую программу проще. Но ПЗУ ведет себя неадекватно, если дергать OE во время ввода адреса. Если же подключить OE через инвертор, то все работает нормально. Каждый второй байт читается нулевым.
То есть один дополнительный корпус, как у меня.
Только это не решает проблему "диагональной" записи загрузчика.
Можно было бы поставить ATMega8 на плату. Она бы и с монитором была бы совместима и адрес сама бы увеличивала. И возможно разархивацией бы занималась. К этой же ATMega вместо ПЗУ можно было бы прикрутить SD-карту.
А начиналось все просто с припаивания ПЗУ к разъему Апогея. Я не нашел маленьких переключателей для линий A16-A19 и впаял регистр. Потом меню нарисовал. Потом архивацию добавил. Сейчас уже мысли об SD-карте. :)
Нет, надо просто ПЗУ прикрутить.
Ниже первые наброски загрузчика. Надо будет не забыть посмотреть, где у Апогея стек расположен. Есть подозрение.
Ничего страшного, можно записать и диагонально. А при распаковке и копировании будут пропускаться адреса, у которых номер столбца и строки равны.
Дополнительный корпус - это не айс, если программно можно обойтись без него, хоть и с извратами.
---------- Post added at 01:37 ---------- Previous post was at 01:35 ----------
Точно ли проверено, что если подсоединить A0 на R/C, а все остальные адреса A1 -> A0, A2 -> A1 и т.д., со смещением, то при чтении массива данных с адреса 0000 по, скажем 00FF, прочтутся парные байты?
Тогда предлагаю такой вот загрузчик.
Загружается в память с адреса 0000 по 00FF, например. Стартует с адреса 0001, т.к. по адресу 0000 мусор.
Таким образом, все байты продублированы. Записан по диагонали во флешке. После запуска, он распаковывает с адреса 0x0011 на адрес 0x0000 уже нормальный вторичный загрузчик, в котором все байты индивидуальные, длина которого может достигать (0x00C2 - 0x0012) / 2 = 88 байт, чего вполне хватит, чтобы загрузить меню с распаковщиком.Код:0000 xx
0001 06 B2 LD B,0xB2 ; B = 0xB2 (Lenght)
0003 B2 OR D
0004 11 11 00 LD DE,0x0011 ; DE = 0x0011 (Source)
0007 00 NOP
0008 62 LD H,D
0009 62 LD H,D
000A 6A LD L,D
000B 6A LD L,D ; HL = 0x0000 (Destination)
000C Е5 PUSH HL
000D Е5 PUSH HL ; 0x0000 -> (SP)
000E C3 C3 00 JP 0x00C3 ; --> 0x00C3
0011 00 NOP
0012 DATA
.. ..
00C1 DATA
00C2 1A LD A,(DE)
00C3 1A LD A,(DE) ; A = (DE)
00C4 13 INC DE
00C5 13 INC DE ; DE = DE + 2
00C6 77 LD (HL),A
00C7 77 LD (HL),A ; (HL) = A
00C8 3A 3A 23 LD A,(0x233A)
00CB 23 INC HL ; HL = HL + 1
00CC 06 DEC B
00CD 06 DEC B ; B = B - 2
00CE C2 C2 00 JP NZ,0x00C2 ; if (B <> 0) goto 0x00C2 -->
00D1 00 NOP
00D2 C9 RET ; goto 0x0000 -->
00D3 C9 RET
Не пинайте сильно, может не до конца разобрался - если R\C просто соединить с А0 - разве не будет читаться?
---------- Post added at 11:53 ---------- Previous post was at 11:46 ----------
Только R\C надо легка задержать, чтобы стабильный адрес записался в ПЗУ.
---------- Post added at 11:55 ---------- Previous post was at 11:53 ----------
И R\С подтянуть резитором к питанию, чтобы после включения сразу на нём была "1"
В последней схеме, которую предложил Titus и под которую я уже переписал все программы, A0 соединен с R/C. Новые данные на выходе ПЗУ появляются только при изменении 0=>1 на входе R/C. То есть только при чтении нечетных адресов. В таком включении программа читается так, что каждый второй байт дублируется. Изначально я почему то подумал, что такую программу написать будет не просто и даже думать не стал, а Titus не поленился и написал загрузчик. Получилось 108 продублированных байт:
06 06 06 06 B2 B2 11 11 00 00 62 62 6A 6A C3 C3
00 00 01 01 FF FF 00 00 21 21 03 03 EE EE 36 36
90 90 2B 2B 2B 2B 70 70 11 11 00 00 F0 F0 3A 3A
1F 1F 00 00 3D 3D BB BB CA CA 25 25 00 00 23 23
...
---------- Post added at 11:14 ---------- Previous post was at 11:06 ----------
А это ведь косяк. При теплой перезагрузке компьютера, на A0 может и не быть 1. Следовательно, не только нулевой байт, но и первый байт может содержать мусор. Надо запускаться с 3-ого адреса. Исправил.
Спешил предложить - недочитал тему...
vinxru,
слушай, а чего к тебя гонки не цветные !?!
тут http://zx.pk.ru/showthread.php?t=9368&page=19 есть цветные
круто ...
http://dl.dropbox.com/u/490774/gonki_color_small.png
заберите к себе полную картинку, а то не аттачится :(
gonki_color.png
gonki_color_small.png
А чего это вода красная, а деревья и футбольное поле желтые?
Я в цвете Апогей еще не подключал.
Я запускал какой-то тест для цветного Апогея, там цвета соответствовали названию.
Я подпаял микросхему и попробовал с помощью монитора загрузить из неё данные. Неожиданный эффект, вроде как по адресам 0,1,2 читается первый байт. То есть можно запускать программу и с нулевого адреса, то есть командой G без параметров.
Косяк. Новый байт появляется по нечетному адресу! А загрузчик мы написали для случая, когда новый байт появлятся по четному адресу...
Тогда лучше первым байтом NOP сделать, а то если в начале будут двухбайтовые команды, то совсем не безразлично, с нулевого или первого байта запускать.
---------- Post added at 23:34 ---------- Previous post was at 23:19 ----------
Логично. Когда R/C падает в ноль, запоминается старшая половина адреса (row), а когда устанавливается в еденицу, происходит выборка по полному адресу (запомненный row и текущий col), а результат защёлкивается в выходном регистре.
Логично то логично. но у всех перед глазами была программа и дампы и никто не обратил внимания.
Теперь будет так:
Код:org 0h
NOP ; 00 Первые три байта идентичны, но они могут не прочитаться.
NOP ; 00
NOP ; 00
LD DE, 11h ; 11 11 00
NOP ; 00
LD H, D ; 62
LD H, D ; 62
LD L, D ; 6A
LD L, D ; 6A
LD BC, 0AE01h ; 01 01 AE (AE - это размер блока данных 0C1h - 13h)
XOR (HL) ; AE
JP 0x00C3 ; C3 C3 00
NOP ; 00
org 013h
DATA-DATA-DATA-DATA-DATA
org 0C1h
DEC HL ; 2B
C2: DEC HL ; 2B
C3: INC DE ; 13
INC DE ; 13
LD A,(DE) ; 1A
LD A,(DE) ; 1A
LD (HL),A ; 77
LD (HL),A ; 77
INC HL ; 23
INC HL ; 23
DEC B ; 05
DEC B ; 05
JP NZ,0x00C2 ; C2 C2 00
NOP ; 00
LD DE, 0xC311 ; 11 11 C3
JP 0 ; C3 00 00
Единственный недостаток этого загрузчика (как, впрочем, и предыдущей его версии) - слишком длинный :)
При 11-битной адресации размер одного ряда будет 2Кб, а загрузчик потребует 107 байт по диагонали, т.е. эта диагональ растянется на 214Кб.
Нужно как можно меньше записать по диагонали, например так:
Данный загрузчик преобразует DATA в нормальный код с адреса 000Dh и запустит его. Правда, размер его может быть всего 19 байт, и располагать его в DATA нужно задом наперёд. Но эти 19 байт могут грузить уже нормально, а не по диагонали.Код:org 1h
LXI H, 21h ; 21 21 00
NOP ; 00
SPHL ; F9
SPHL ; F9
DCX H ; 2B
L0008: DCX H ; 2B
POP PSW ; F1
POP PSW ; F1
MOV M,A ; 77
MOV M,A ; 77
RST 1 ; CF
RST 1 ; CF
DS 14h ; 20 любых байт
L0023: DATA-DATA-DATA
Вот пример:
Итого, по диагонали будет записано всего 39 байт, т.е. в пределах 80КбКод:org 0Dh
LXI H, 0EE01h ; 21 01 EE
POP B ; C1 берём из DATA адрес, куда загружать, например 8080h
POP D ; D1 инициализируем регистр E из DATA, должно быть 0000h
L0012: MOV M,E ; 73 row = E/2
MVI M,1 ; 36 01 col = 0
LDA 0EE00h ; 3A 00 EE читаем байт
STAX B ; 02 сохраняем
INX B ; 03
INR E ; 1C E=E+2
INR E ; 1C
RZ ; C8 если ноль (загрузили 128 байт), то переходим по адресу из DATA, должно совпадать с началом вторичного загрузчика, например 8080h
JMP L0012 ; C3 12 00 на начало цикла
L0020:
Недостатки:
- нужно запускать по адресу 0001
- грузит только 128 байт, т.е. нужно догружать остаток
Не будет. Загрузчик займет именно столько байт, сколько для него требуется. А при загрузки самих игр данные байты с адресом строки равным адресу колонки, будут пропускаться. Таким образом, теряем только 2кб.
---------- Post added at 14:07 ---------- Previous post was at 13:58 ----------
Хороший загрузчик, хитрый)Цитата:
Нужно как можно меньше записать по диагонали, например так:
Код:org 1h
LXI H, 21h ; 21 21 00
NOP ; 00
SPHL ; F9
SPHL ; F9
DCX H ; 2B
L0008: DCX H ; 2B
POP PSW ; F1
POP PSW ; F1
MOV M,A ; 77
MOV M,A ; 77
RST 1 ; CF
RST 1 ; CF
DS 14h ; 20 любых байт
L0023: DATA-DATA-DATA
Программа последовательно читает ПЗУ, пропускает 128 байтный загрузчик расположенный по диагонали. Пропускается 1 байт из 2048. В ПЗУ 256 Кб теряется 128 байт, в ПЗУ 512 Кб теряется 256 байт.
Инициализация:
V_BANKL1 = банк * 2
V_BANKL2 = банк * 2 + 1
V_BANKH1 = (банк * 2) >> 8
DE = (смещение * 2) | 0xF000
Код:; Чтение байта из ПЗУ
; Вызывающая программа хранит и не изменяет DE.
; DE - это смещение от F000 до FFFF c шагом 2.
READBYTE: LD A, D
LD (0EE02h), A
LD A, E
V_BANKL1: CP 0 ; тут находятся 7 бит банка (*2)
JP Z, IGNOREBYTE ; Пропускаем диагональные байты
NOIGNOREBYTE: LD (0EE01h), A
V_BANKH1: LD A, 0 ; тут находится старший бит банка
LD (0EE02h), A
V_BANKL2: LD A, 1 ; тут находится 7 бит банка (*2+1)
LD (0EE01h), A
LD A, (0EE00h)
INC E
INC E
RET NZ
;----------------------------------------------------------------------------
; Пересекли границу 128 байт
INCBANK: INC D
RET NZ
; Пересекли границу 2048 байт
; Выводим прогресс
PUSH DE
PUSH BC
ld c, '.'
call 0F809h
POP BC
POP DE
; Увеличиваем счетчики банков
PUSH AF
LD A, (V_BANKL2+1)
INC A
JP Z, INCBANK1
INCBANK2: LD (V_BANKL1+1), A
INC A
LD (V_BANKL2+1), A
POP AF
; Адрес чтения
LD DE, 0F000h
RET
;----------------------------------------------------------------------------
; Пересекли границу 256 Кб
INCBANK1: PUSH HL
LD HL, V_BANKH1+1
INC (HL)
POP HL
JP INCBANK2
;----------------------------------------------------------------------------
; Пропускаем диагональные байты
IGNOREBYTE: LD A, D ; Пропускаем только адреса 0-128
AND 0Fh
LD A, E
JP NZ, NOIGNOREBYTE
INC E
INC E
CALL Z, INCBANK
JP READBYTE
Киньте кто-нить пару-тройку ромов от апогея, и скажите, сколько они занимают ужатые. Хочу со своим пакером сравнить.
Скачай MegaLZ, да возьми любые файлы, хоть от РК, хоть от Апогея. Запакуй и сравни.
Я оптимизировал депакер для ВМ80.
Вот, сбацал конфиг, для демонстрации вышеизложенного "хитрого" загрузчика. Незнаю, насколько точно эмулируется 49LF004, но загрузчик работает. Единственное, что не нравится, при загрузке из монитора конечный адрес должен быть нечётный, т.е. типа так:
R0,4F
G1