Что ж, решение все-таки через индексную пару. Добавляет 40 тактов к каждой линии, но это лучший вариант из имеющихся.
Ограничения: пара AF портится, если идет переброс; пара BC задействована под "резервные" байты при смене стека.
В начале вывода каждой строки (линии) добавляется две команды:
Код:
ADD IY,DE
LD B,(IY-1) ;в паре BC будет 2 байта
LD C,(IY-2) ;под "новым" стеком
LD SP,IY
Сам обработчик тоже переделан из-за дополнительных проверок:
Код:
INTERR LD (CURRSP+1),SP
LD SP,INTBUF+100
PUSH AF,BC,DE,HL... ;сохраняем все изменяемые регистры
BLABLA ;процедуры на прерываниях
......
POP ...HL,DE,BC ;восстанавливаем, кроме AF
LD A,(CURRSP+2) ;старший байт стека
RLA ;если SP>=#8000 - идет переброс
JR C,CURRSP
POP AF ;иначе нормальный выход
LD SP,(CURRSP+1)
EI
RET
CURRSP LD SP,0 ;пару AF в коде вывода не используем!
POP HL ;адрес возврата в процедуру вывода
LD (RET_JP+1),HL
DEC HL
LD A,(HL) ;если последней выполненной
CP #F9 ;командой было LD SP,IY
JR NZ,RET_JP-6 ;то восстанавливаем из BC
DEC HL ;проверяем оба байта
LD A,(HL) ;для надежности
CP #FD ;#FDF9 для IY или #DDF9 для IX
JR NZ,$+6
PUSH BC ;восстанавливаем из BC
POP BC
JR $+7
LD HL,(INTBUF+92)
PUSH HL ;иначе востанавливаем из HL
POP HL
EI
RET_JP JP 0
INTBUF DEFS 100 ;буфер стека
Логика работы: обработчик смотрит, где стек, если переброса нет - нормальный выход.
Если переброс и последняя выполненная команда была LD SP,IY - в стек бросается заранее взятая ниже пара BC.
Иначе бросается HL, что даст верное восстановление хоть до, хоть после смены стека.
Можно схитрить: если карта начинает выводиться сразу после обработки прерывания (после HALT),
то в код вывода "первого куска" загрузку BC из IY можно не вставлять - кусок точно успеет вывестись до прерывания.
Каждая загрузка 40 тактов (с wait), х40 = 1600т на куске. х4 = 6400, поэтому смысл экономить есть.